package com.zz.server.handle.defaults;

import com.zz.common.annotation.Executor;
import com.zz.common.config.Constants;
import com.zz.common.datasource.DataSource;
import com.zz.common.datasource.DataSourceFactory;
import com.zz.common.entity.Information;
import com.zz.common.entity.Meta;
import com.zz.common.entity.ProtocolInfo;
import com.zz.common.enums.MessageType;
import com.zz.common.enums.SerializationType;
import com.zz.common.handle.executor.AbstractMessageExecutor;
import com.zz.common.protocol.DefaultProtocol;
import com.zz.common.utils.ObjectUtil;
import com.zz.common.utils.SnowflakeUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.internal.EmptyArrays;
import lombok.extern.slf4j.Slf4j;

import java.util.Optional;

/**
 * 数据转发
 */
@Slf4j
@Executor(msgType = MessageType.TYPE_TRANSFER)
public class TransferExecutor extends AbstractMessageExecutor {

    private final DataSource dataSource = DataSourceFactory.getTunnelSource();

    @Override
    public void execute(Information information) {
        ChannelHandlerContext context = information.getContext();
        DefaultProtocol protocol = (DefaultProtocol) information.getProtocolMsg();
        Channel localChannel = context.channel().attr(Constants.Attributes.LOCAL_CHANNEL).get();
        if (ObjectUtil.isNull(localChannel)) {
            log.error("local channel is null");
            return;
        }
        localChannel.writeAndFlush(Optional.ofNullable(protocol.getData()).orElse(EmptyArrays.EMPTY_BYTES));

    }

    @Override
    public void execute(ProtocolInfo protocolInfo) {
        // 构建连接消息
        DefaultProtocol protocolMsg = DefaultProtocol.builder().type(MessageType.TYPE_TRANSFER)
                .serialNumber(SnowflakeUtil.genSnowflakeId())
                .serializationType(SerializationType.PROTOSTUFF)
                .data(protocolInfo.getData())
                .meta(Meta.builder().clientId(protocolInfo.getClientId())
                        .localChannelId(protocolInfo.getContext().channel().id().asLongText())
                        .serverChannelId(protocolInfo.getServerChannel().id().asLongText())
                        .config(dataSource.getClientConfigIdByDomain(protocolInfo.getDomain())).build())
                .build();

        protocolInfo.getServerChannel().writeAndFlush(protocolMsg);
    }
}
